#include "tuya_ble_sdk_demo.h"
#include "tuya_ble_ota.h"
#include "ty_ble.h"
#include "ty_rtc.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_api.h"
#include "tuya_ble_log.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_unix_time.h"
#include "tuya_ble_sdk_test.h"
#include "tuya_ble_feature_weather.h"
#include "tuya_ble_bulk_data_demo.h"
#include "tuya_ble_app_uart_common_handler.h"
#include "co_debug.h"
#include "tuya_ble_api.h"
#include "ble_comp.h"
#include "device.h"


#pragma pack(1)
typedef struct
{
    open_meth_t meth;
    reg_stage_t stage;
    uint8_t hardid;
    uint8_t reg_idx;
    uint8_t result;
} creat_sub_report_t;

typedef struct
{
    uint8_t dp_id;
    uint32_t hardid;
} open_record_report_t;

typedef struct
{
    uint8_t dp_id;
    uint32_t dp_data_len;
    uint8_t dp_data[256];
} open_record_report_common_t;

static struct 
{
    uint8_t type;
    union
    {
        creat_sub_report_t creat_sub_report;
        open_record_report_t open_record_report;
        open_record_report_common_t open_record_report_common;
    };
} delay_report_param;
#pragma pack()


/*********************************************************************
 * LOCAL CONSTANT
 */

/*********************************************************************
 * LOCAL STRUCT
 */

/*********************************************************************
 * LOCAL VARIABLE
 */
static const char auth_key_test[]  = TY_DEVICE_AUTH_KEY;
static const char device_id_test[] = TY_DEVICE_DID;

//tuya_ble_sdk init param
static tuya_ble_device_param_t tuya_ble_device_param = {
    .use_ext_license_key = 1, //1-info in tuya_ble_sdk_demo.h, 0-auth info
    .device_id_len       = DEVICE_ID_LEN, //DEVICE_ID_LEN,
    .p_type              = TUYA_BLE_PRODUCT_ID_TYPE_PID,
    .product_id_len      = 8,
    .adv_local_name_len  = 4,
    .firmware_version    = TY_DEVICE_FVER_NUM,
    .hardware_version    = TY_DEVICE_HVER_NUM,
};

static tuya_ble_timer_t disconnect_timer;
static tuya_ble_timer_t update_conn_param_timer;
static tuya_ble_timer_t lock_timer_delay_report_timer;
extern uint32_t OSAL_GetTickCount(void);

tuya_ble_app_master_result_handler_t tuya_ble_app_master_result_handler;

/*********************************************************************
 * VARIABLE
 */
demo_dp_t g_cmd;
demo_dp_t g_rsp;


void cpt_reverse_byte(void* buf, uint32_t size)  //大小端转换
{
    uint8_t* p_tmp = buf;
    uint8_t  tmp;
    for(uint32_t idx=0; idx<size/2; idx++)
    {
        tmp = *(p_tmp+idx);
        *(p_tmp+idx) = *(p_tmp+size-1-idx);
        *(p_tmp+size-1-idx) = tmp;
    }
}


void app_port_reverse_byte(void* buf, uint32_t size)
{
    cpt_reverse_byte(buf, size);
}

uint32_t app_port_dp_data_report(uint8_t *buf, uint32_t size)
{
    if(tuya_ble_connect_status_get() == BONDING_CONN)
    {
        TUYA_APP_LOG_HEXDUMP_DEBUG("app_port_dp_data_report=dp_rsp", buf, size);
        return tuya_ble_dp_data_send(0,DP_SEND_TYPE_ACTIVE,DP_SEND_FOR_CLOUD_PANEL,DP_SEND_WITHOUT_RESPONSE,buf,(size));
    } else {
        TUYA_APP_LOG_HEXDUMP_DEBUG("dp_rsp_unconn", buf, size);
        return TUYA_BLE_ERR_INTERNAL;
    }
}


/*********************************************************************
 * LOCAL FUNCTION
 */


//uint32_t app_port_dp_data_with_time_report(uint32_t timestamp, uint8_t *buf, uint32_t size)
//{ 
////    TUYA_APP_LOG_INFO("timestamp: %d", timestamp);
//	  //SendDataToBackBoard(EventOpenclose_GetRtcTime,(uint8_t *)&timestamp,4);//ADD	
//	 // app_port_update_timestamp(timestamp);
//    if(tuya_ble_connect_status_get() == BONDING_CONN)
//    {
//        //TUYA_APP_LOG_INFO("timestamp: %d", timestamp);
//        TUYA_APP_LOG_HEXDUMP_DEBUG("app_port_dp_data_with_time ", buf, size);		  
//        return tuya_ble_dp_data_with_time_send(0,0,0,timestamp, buf, size);
//    } else {
//        //TUYA_APP_LOG_INFO("timestamp: %d", timestamp);
//        TUYA_APP_LOG_HEXDUMP_DEBUG("dp_rsp_timestamp_unconn", buf, size);
//        return TUYA_BLE_ERR_INTERNAL;
//    }
//}





// static void delay_report_outtime_handler(tuya_ble_timer_t timer)
//{
//            lock_open_record_report_common(delay_report_param.open_record_report_common.dp_id,
//                                     delay_report_param.open_record_report_common.dp_data,
//                                     delay_report_param.open_record_report_common.dp_data_len);
//}

/*********************************************************
FN: 
*/
//uint32_t lock_open_record_report_with_delay(uint8_t dp_id, uint32_t hardid)
//{
//    TUYA_APP_LOG_INFO("Lock_open_record_report_with_delay");
//    delay_report_param.type = DELAY_REPORT_TYPE_OPEN_RECORD_REPORT;
//    delay_report_param.open_record_report.dp_id = dp_id;
//    delay_report_param.open_record_report.hardid = hardid;
//    tuya_ble_timer_start(lock_timer_delay_report_timer);
//    return TUYA_BLE_SUCCESS;
//}







uint32_t lock_state_sync_report(uint8_t dp_id, uint32_t data,uint8_t mode)   //电量上报完成240912
{   uint8_t len;
    g_rsp.dp_id = dp_id;
      
    switch(dp_id)
    { 
        //dp_type = value
        case WR_SET_TIMER_LOCK:
        case WR_SET_TIMER_AUTO_LOCK:
        case OR_STS_AUTH_LOCK_OUTTIME:
        case OR_STS_BATTERY_PERCENT: {
            g_rsp.dp_type = APP_PORT_DT_VALUE;
            g_rsp.dp_data_len = APP_PORT_DT_VALUE_LEN;
            g_rsp.dp_data[0] = data>>24;
            g_rsp.dp_data[1] = data>>16;
            g_rsp.dp_data[2] = data>>8;
            g_rsp.dp_data[3] = data;
        } break;
        
        //dp_type = enum, but data is value, compatible with OR_BATTERY_PERCENT
				
        case OR_STS_BATTERY_POSITION: {
            g_rsp.dp_type = APP_PORT_DT_ENUM;
            g_rsp.dp_data_len = APP_PORT_DT_ENUM_LEN;
            g_rsp.dp_data[0] = data>>24;
            g_rsp.dp_data[1] = data>>16;
            g_rsp.dp_data[2] = data>>8;
            g_rsp.dp_data[3] = data;
        } break;

        //dp_type = enum
	    case WR_SET_COMBINE_LOCK:		
		case WR_SET_NAVIGATE_VOLUME:
        case WR_SET_LOCK_LANGUAGE: //ADD
            g_rsp.dp_type = APP_PORT_DT_ENUM;
            g_rsp.dp_data_len = APP_PORT_DT_ENUM_LEN;
            g_rsp.dp_data[0] = data;
         break;
        
        //dp_type = bool
        case WR_SET_HAND_LOCK:
		case OR_STS_DOOR_STATE: 
		case WR_SET_AUTO_LOCK_SWITCH:
        case OR_STS_CHILD_LOCK:
        case OR_STS_ANTI_LOCK:
        case WR_STS_REVERSE_LOCK:
        case OR_STS_DOORBELL_RING:
        case OR_STS_LOCK_STATE: {
            g_rsp.dp_type = APP_PORT_DT_BOOL;
            g_rsp.dp_data_len = APP_PORT_DT_BOOL_LEN;
            g_rsp.dp_data[0] = data;
        } break;
        
        case OR_LOG_OPEN_WITH_BT: //开门记录上报
            g_rsp.dp_type = APP_PORT_DT_VALUE;
            g_rsp.dp_data_len = APP_PORT_DT_VALUE_LEN;
            
            g_rsp.dp_data[0] = data>>24;
            g_rsp.dp_data[1] = data>>16;
            g_rsp.dp_data[2] = data>>8;
            g_rsp.dp_data[3] = data;
            
        break;  
        
        case WR_STS_CLOSE_RECORD: //关门记录上报
            //x00：未定义 xxx 关锁
            //0x01：手机远程关锁
            //0x02：语音远程关锁
            //0x03：地理围栏关锁
            //0x04：App 长按关锁
            //0x05：配件关锁
            //0x06：自动落锁
            //0x07：本地手动落锁 
            g_rsp.dp_type = APP_PORT_DT_RAW;
            g_rsp.dp_data_len = APP_PORT_DT_BITMAP; //5;
            
            g_rsp.dp_data[0] = mode;   //上锁方式      
            g_rsp.dp_data[1] = data>>24;
            g_rsp.dp_data[2] = data>>16;
            g_rsp.dp_data[3] = data>>8;
            g_rsp.dp_data[4] = data;
            
        break; 
        
        
        
        default: {
        } break;
    }
    len = g_rsp.dp_data_len;
    app_port_reverse_byte(&g_rsp.dp_data_len, 2);//上报的长度，大端模式（高地址存低位数据），需要改为小端模式（高地址存高位数据） 否则：MTP_OK != ret
  
    return app_port_dp_data_report((void*)&g_rsp.dp_id, (4 + len));
}


uint32_t lock_open_report_common(uint8_t dp_id, uint8_t open_meth)
{
	uint32_t timestamp;
     uint8_t len;
    ty_rtc_get_time(&timestamp);
    g_rsp.dp_id = dp_id;
    g_rsp.dp_type = APP_PORT_DT_RAW;
    //g_rsp.dp_data_len = dp_data_len;
    //memcpy(g_rsp.dp_data, dp_data, dp_data_len);
    
 //   lock_evt_save(timestamp, (void*)&g_rsp, (OFFLINE_RECORD_LEN));
    
//    if(g_current_master_id != 0xFFFF) {
//        return TUYA_BLE_ERR_INTERNAL;
//    }
    len = g_rsp.dp_data_len;
    app_port_reverse_byte(&g_rsp.dp_data_len, 2);
    
    g_rsp.dp_data[18] = 0;  //上报结果
    TUYA_APP_LOG_HEXDUMP_DEBUG("lock_open_record_report_common", &g_rsp.dp_id, (len+4));
    
    return app_port_dp_data_report(&g_rsp.dp_id,(4 + len));
}




/*********************************************************
FN: 
*/
extern uint32_t dp_ack_sn;
extern uint32_t cmd_ack_sn;
static uint32_t open_with_master_handler(void* cmd_dp_data, void* rsp_dp_data, uint8_t* rsp_dp_data_len,uint8_t *dp_data,uint8_t len)
{
    open_with_master_t* cmd = cmd_dp_data;  
    open_with_master_result_t* rsp = rsp_dp_data;
    uint8_t *rsp_len=rsp_dp_data_len;
    
    app_port_reverse_byte(&cmd->masterid, 2);
    app_port_reverse_byte(&cmd->slaveid, 2);
    rsp->masterid = cmd->masterid;
    rsp->slaveid = cmd->slaveid;
    app_port_reverse_byte(&rsp->masterid, 2);
    app_port_reverse_byte(&rsp->slaveid, 2);


    if(cmd->operation > 0x01) {
        rsp->result = 0x05;
        goto OPEN_WITH_MASTER_RESPONSE;
    }


    if(cmd->operation == 0x01) 
    {    
        rsp->result = 0x00; 
        lock_open_report_common(WR_BSC_OPEN_WITH_MASTER, cmd->open_meth_info[0]);
        lock_state_sync_report(OR_LOG_OPEN_WITH_BT, 0,NULL); //开锁上报，实际应该等到开门结束后，才上报。
        Ble_OpenCloseHandler(0x47); 
    }
    
OPEN_WITH_MASTER_RESPONSE:
    if(rsp->result != 0x00) {
        TUYA_APP_LOG_INFO("open_with_master result: %d", rsp->result);
    }
    *rsp_len = sizeof(open_with_master_result_t);
    
    return TUYA_BLE_SUCCESS;  
}


static uint32_t close_with_master_handler(void* rsp_dp_data)
{

      Ble_OpenCloseHandler(0x2e); 
      lock_state_sync_report(WR_SET_HAND_LOCK, 1,NULL);     //蓝牙关锁应答
//      lock_state_sync_report(WR_STS_CLOSE_RECORD, 0x07,0x04);  //蓝牙关锁记录上报
      
      return TUYA_BLE_SUCCESS;  
}


void lock_hard_creat_sub_report(uint8_t meth, uint8_t stage, uint8_t hardid, uint8_t reg_idx, uint8_t result)
{
    open_meth_creat_result_t* rsp = (void*)g_rsp.dp_data;
    uint8_t  len;
    rsp->stage = (reg_stage_t)stage;
    rsp->hardid = hardid;
    rsp->reg_num = reg_idx;
    rsp->result = result;
    g_rsp.dp_data_len = sizeof(open_meth_creat_result_t);
    
    len = g_rsp.dp_data_len;
    app_port_reverse_byte(&g_rsp.dp_data_len, 2);
    
    app_port_dp_data_report((uint8_t *)&g_rsp.dp_id, (4 + len));
}


 uint32_t hardid=0;  
 static uint32_t open_meth_creat_handler(void* cmd_dp_data, void* rsp_dp_data, uint8_t* rsp_dp_data_len)
{
    open_meth_creat_t* cmd = cmd_dp_data;
    open_meth_creat_result_t* rsp = rsp_dp_data;
    if(hardid<10) hardid++;
    lock_hard_creat_sub_report(cmd->meth, REG_STAGE_COMPLETE, hardid, REG_NOUSE_DEFAULT_VALUE, REG_NOUSE_DEFAULT_VALUE);
    
    //*rsp_len = sizeof(open_meth_creat_result_t);
    
    return TUYA_BLE_SUCCESS;
}



static uint32_t open_meth_delete_handler(void* cmd_dp_data, void* rsp_dp_data, uint8_t* rsp_dp_data_len)
{
    open_meth_delete_t* cmd = cmd_dp_data;
    open_meth_delete_result_t* rsp = rsp_dp_data;
    uint8_t* rsp_len = rsp_dp_data_len;
    uint8_t ret = TUYA_BLE_SUCCESS;
    uint8_t  len;
    len = g_rsp.dp_data_len = sizeof(open_meth_delete_result_t);
    
    TUYA_APP_LOG_INFO("open_meth_delete_handler id=%d",cmd->hardid);
    
    cmd->hardid-=1;
    ret = TUYA_BLE_SUCCESS;
    
    #if 0
    switch(cmd->meth)
    {
        case OPEN_METH_BASE: {
            ret += lock_hard_delete_all_by_memberid(cmd->memberid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_BASE delete start"); }
        } break;
        
        case OPEN_METH_PASSWORD: {
            ret += lock_hard_delete(cmd->hardid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_PASSWORD delete start"); }
        } break;
        
        case OPEN_METH_DOORCARD: {
            ret += lock_hard_delete(cmd->hardid);
            ret += lock_hard_doorcard_delete(cmd->hardid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_DOORCARD delete start"); }
        } break;
        
        case OPEN_METH_FINGER: {
					  ret=DelectSigleFingerUser(cmd->hardid+1,cmd->admin_falg);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_FINGER delete start"); }
        } break;
        
        case OPEN_METH_FACE: {
            ret += lock_hard_delete(cmd->hardid);
            ret += lock_hard_face_delete(cmd->hardid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_FACE delete start"); }
        } break;
        
        case OPEN_METH_PALM: {
            ret += lock_hard_delete(cmd->hardid);
            ret += lock_hard_palm_delete(cmd->hardid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_PALM delete start"); }
        } break;
        
        case OPEN_METH_VEIN: {
            ret += lock_hard_delete(cmd->hardid);
            ret += lock_hard_vein_delete(cmd->hardid);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_VEIN delete start"); }
        } break;
        
        default: {
        } break;
    }
    #endif 
    
    
    if(ret == TUYA_BLE_SUCCESS) {
        rsp->result = 0xFF; //delete success
    } else if(ret == TUYA_BLE_ERR_NOT_FOUND) {
        rsp->result = 0x01; //delete fail
    } else {
        rsp->result = 0x00; //delete fail
    }
    *rsp_len = sizeof(open_meth_delete_result_t); 
    
    app_port_reverse_byte(&g_rsp.dp_data_len, 2);
    
    app_port_dp_data_report((void*)&g_rsp.dp_id, (4+len));
    
    return TUYA_BLE_SUCCESS;
}


static uint32_t open_meth_modify_handler(void* cmd_dp_data, void* rsp_dp_data, uint8_t* rsp_dp_data_len)
{
    open_meth_modify_t* cmd = cmd_dp_data;
    open_meth_modify_result_t* rsp = rsp_dp_data;
    uint8_t* rsp_len = rsp_dp_data_len;
    uint8_t len,ret = TUYA_BLE_SUCCESS;
	#if 0
    switch(cmd->meth)
    {
        case OPEN_METH_BASE: {
            ret = lock_hard_modify_all_by_memberid(cmd->memberid, cmd->time);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_BASE modify start"); }
        } break;
        
        case OPEN_METH_PASSWORD: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_PASSWORD modify start"); }
        } break;
        
        case OPEN_METH_DOORCARD: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_DOORCARD modify start"); }
        } break;
        
        case OPEN_METH_FINGER: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_FINGER modify start"); }
        } break;
        
        case OPEN_METH_FACE: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_FACE modify start"); }
        } break;
        
        case OPEN_METH_PALM: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_PALM modify start"); }
        } break;
        
        case OPEN_METH_VEIN: {
            ret = lock_hard_modify_in_local_flash(cmd->meth);
            if(ret == TUYA_BLE_SUCCESS) {
                TUYA_APP_LOG_INFO("OPEN_METH_VEIN modify start"); }
        } break;
        
        default: {
        } break;
    }
    
     #endif 
     
    rsp->cycle = cmd->cycle;
    if(ret == TUYA_BLE_SUCCESS) {
        rsp->result = 0xFF; //modify success
    } else {
        rsp->result = 0x00; //modify fail
    }
    *rsp_len = sizeof(open_meth_modify_result_t);
    
    len = g_rsp.dp_data_len;
    app_port_reverse_byte(&g_rsp.dp_data_len, 2);
    
    app_port_dp_data_report((void*)&g_rsp.dp_id, (len));
    
    return TUYA_BLE_SUCCESS;
}




extern uint8_t get_battery(void);
uint32_t lock_dp_parser_handler(void* dp_data,uint16_t len)
{
    uint8_t rsp_flag = 1;
     
    memset(&g_cmd.dp_id, 0, sizeof(demo_dp_t));
	  memset(&g_rsp.dp_id, 0, sizeof(demo_dp_t));
    //init cmd and rsp
    memcpy(&g_cmd, dp_data, sizeof(demo_dp_t));
    memcpy(&g_rsp, dp_data, sizeof(demo_dp_t));
    g_rsp.dp_data_len= g_cmd.dp_data_len=len-4;
    
    //TUYA_APP_LOG_INFO("lock_dp_parser_handler");
    TUYA_APP_LOG_HEXDUMP_DEBUG("lock_dp_parser_handler", &g_rsp.dp_id, g_rsp.dp_data_len+4);
    
    switch(g_cmd.dp_id)  //每个DP点功能，涉及到上层操作及FLAS操作，此处未做处理， 只做应答
    {
        case WR_BSC_OPEN_METH_CREATE: {
              TUYA_APP_LOG_INFO("WR_BSC_OPEN_METH_CREATE"); //添加密码
              open_meth_creat_handler(g_cmd.dp_data, g_rsp.dp_data, &g_rsp.dp_data_len);
        } break;
        
        case WR_BSC_OPEN_METH_DELETE: {
              TUYA_APP_LOG_INFO("WR_BSC_OPEN_METH_DELETE"); //删除密码
              open_meth_delete_handler(g_cmd.dp_data, g_rsp.dp_data, &g_rsp.dp_data_len);
              len = g_rsp.dp_data_len + 4;
        } break;
    
        case WR_BSC_OPEN_METH_MODIFY: {
            TUYA_APP_LOG_INFO("WR_BSC_OPEN_METH_MODIFY"); //修改密码
            open_meth_modify_handler(g_cmd.dp_data, g_rsp.dp_data, &g_rsp.dp_data_len);
            len = g_rsp.dp_data_len + 4;
        } break;
    
    
        case WR_BSC_OPEN_METH_SYNC:   {
            TUYA_APP_LOG_INFO("OPEN_METH sync start");

        } break;
        
        case WR_BSC_OPEN_METH_SYNC_NEW: {
            TUYA_APP_LOG_INFO("WR_BSC_OPEN_METH_SYNC_NEW");

        } break;
    
        
        case WR_SET_LOCK_LANGUAGE: {  
             TUYA_APP_LOG_INFO("WR_SET_LOCK_LANGUAGE");  //导航语言设置
             lock_state_sync_report(WR_SET_LOCK_LANGUAGE,g_rsp.dp_data[0],NULL);
        } break;      
        
        case WR_SET_NAVIGATE_VOLUME: {  
             TUYA_APP_LOG_INFO("WR_SET_NAVIGATE_VOLUME");  //导航语音音量设置
             lock_state_sync_report(WR_SET_NAVIGATE_VOLUME,g_rsp.dp_data[0],NULL);
        } break; 
        
        
        case WR_SET_AUTO_LOCK_SWITCH: {  
             TUYA_APP_LOG_INFO("WR_SET_AUTO_LOCK_SWITCH");  //自动关锁
             lock_state_sync_report(WR_SET_AUTO_LOCK_SWITCH,g_rsp.dp_data[0],NULL);
        } break; 
        
        case WR_SET_COMBINE_LOCK: {  
             TUYA_APP_LOG_INFO("WR_SET_COMBINE_LOCK");//组合开锁方式设置
             lock_state_sync_report(WR_SET_COMBINE_LOCK,g_rsp.dp_data[0],NULL);
        } break; 
        
        case WR_SET_TIMER_LOCK: {  
             TUYA_APP_LOG_INFO("WR_SET_TIMER_LOCK");  //自动关锁时间设置
             uint32_t value;
             value = (g_cmd.dp_data[0]<<24) + (g_cmd.dp_data[1]<<16) + (g_cmd.dp_data[2]<<8) + g_cmd.dp_data[3];
             lock_state_sync_report(WR_SET_TIMER_LOCK,value,NULL);
        } break; 
        
        
        case WR_SET_TIMER_AUTO_LOCK: {  
             TUYA_APP_LOG_INFO("WR_SET_TIMER_AUTO_LOCK");
    
        } break;    
        
    
        case WR_BSC_OPEN_WITH_MASTER: 
        {
            TUYA_APP_LOG_INFO("WR_BSC_OPEN_WITH_MASTER");
            open_with_master_handler(g_cmd.dp_data, g_rsp.dp_data, &g_rsp.dp_data_len,dp_data,len);
        } break;
               
        case WR_SET_HAND_LOCK: {
            TUYA_APP_LOG_INFO("WR_SET_HAND_LOCK");
            //if((g_cmd.dp_data_len == 1) && (g_cmd.dp_data[0] == 0x01))
            {  
                close_with_master_handler(&g_rsp.dp_data);
                rsp_flag=0;
            }
        } break;
        
        
        case WR_BSC_SET_MASTER_SRAND_NUM: {
             TUYA_APP_LOG_INFO("WR_BSC_SET_MASTER_SRAND_NUM");
        } break; 
        
        
        
    }
    
    if(rsp_flag && (g_rsp.dp_data_len > 0))
    {
        //app_port_dp_data_report((void*)&g_rsp.dp_id, (4 + g_rsp.dp_data_len));
        lock_state_sync_report(OR_STS_BATTERY_PERCENT,get_battery(),NULL);
        
    }
    
}


void app_gap_dis_connected_handler(uint8_t status)
{
    Device_IRQHandler(vBLE_0, &status, (PUBLISH_BLE_STATUS << 16) | 1);
}

/*********************************************************
FN: 
*/
static void tuya_ble_sdk_callback(tuya_ble_cb_evt_param_t* event)
{
    TUYA_APP_LOG_DEBUG("callback: %02x", event->evt);


    switch(event->evt)
    {
        case TUYA_BLE_CB_EVT_CONNECTE_STATUS: {
//#if TUYA_BLE_SDK_TEST
//            tuya_ble_sdk_test_send(TY_UARTV_CMD_GET_DEVICE_STATE, (void*)&event->connect_status, sizeof(uint8_t));
//#endif
            
            if(event->connect_status == BONDING_CONN) {
                TUYA_APP_LOG_INFO("bonding and connecting");  //used  
                tuya_ble_update_conn_param_timer_start();
                app_gap_dis_connected_handler(1);
            }
            else
            {
                app_gap_dis_connected_handler(0);//蓝牙断开上报
            }
        } break;
            
        case TUYA_BLE_CB_EVT_DP_DATA_RECEIVED : {
        TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DP_DATA_RECEIVED_1");  //used
            //tuya_ble_common_uart_send_cmd(event->dp_received_data.p_data, event->dp_received_data.data_len);
#if TUYA_BLE_SDK_TEST
            //tuya_ble_sdk_test_send(TY_UARTV_CMD_DP_WRITE, event->dp_received_data.p_data, event->dp_received_data.data_len);
            Device_IRQHandler(vBLE_0, event->dp_received_data.p_data, (PUBLISH_APP_CMD << 16) | (event->dp_received_data.data_len)); //改为OS回调
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_DP_DATA_SEND_RESPONSE: {
        TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DP_DATA_SEND_RESPONSE_2"); //used
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_dp_report_handler();
            tuya_ble_sdk_test_send(TY_UARTV_CMD_DP_RSP, &event->dp_send_response_data.status, sizeof(uint8_t));
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_DP_DATA_WITH_TIME_SEND_RESPONSE: {
        TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DP_DATA_WITH_TIME_SEND_RESPONSE");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_dp_report_handler();
            tuya_ble_sdk_test_send(TY_UARTV_CMD_DP_RSP, &event->dp_with_time_send_response_data.status, sizeof(uint8_t));
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_TIME_STAMP: {  TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_TIME_STAMP");  //used
            uint32_t timestamp_s = tuya_ble_ascii_to_int((void*)event->timestamp_data.timestamp_string, 10);
            uint32_t timestamp_ms = tuya_ble_ascii_to_int((void*)(event->timestamp_data.timestamp_string+10), 3);
            
            uint64_t timestamp = 0;
            timestamp = timestamp_s*1000 + timestamp_ms;
            
            ty_rtc_set_time(timestamp_s);
            
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_TIME_STAMP - time_zone: %d", event->timestamp_data.time_zone);
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_TIME_STAMP - timestamp: %d", timestamp_s);
            
#if TUYA_BLE_SDK_TEST
            tuya_ble_time_struct_data_t data = {0};;
            tuya_ble_utc_sec_2_mytime(timestamp_s, &data, false);
            
            tuya_ble_time_noraml_data_t normal_data = {0};
            memcpy(&normal_data, &data, sizeof(tuya_ble_time_struct_data_t));
            normal_data.time_zone = event->timestamp_data.time_zone;
            
            tuya_ble_sdk_test_get_time_rsp(&normal_data);
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_TIME_NORMAL:
        case TUYA_BLE_CB_EVT_APP_LOCAL_TIME_NORMAL: {   TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_TIME_NORMAL");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_get_time_rsp(&event->time_normal_data);
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_UNBOUND: {      TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_UNBOUND");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_unbind_mode_rsp(0);
#endif
            
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_UNBOUND");
        } break;
        
        case TUYA_BLE_CB_EVT_ANOMALY_UNBOUND: {   TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_ANOMALY_UNBOUND");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_unbind_mode_rsp(1);
#endif

            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_ANOMALY_UNBOUND");
        } break;
        
        case TUYA_BLE_CB_EVT_DEVICE_RESET: {    TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DEVICE_RESET");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_unbind_mode_rsp(2);
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE: {
#if TUYA_BLE_SDK_TEST
            if(event->reset_response_data.type == RESET_TYPE_UNBIND) {
                if(event->reset_response_data.status == 0) {
                    tuya_ble_sdk_test_unbind_mode_rsp(3);
                }
            } else if(event->reset_response_data.type == RESET_TYPE_FACTORY_RESET) {
                if(event->reset_response_data.status == 0) {
                    tuya_ble_sdk_test_unbind_mode_rsp(4);
                }
            }
#endif
            
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE");
        } break;
        
        case TUYA_BLE_CB_EVT_DP_QUERY: {    TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DP_QUERY");
//            TUYA_APP_LOG_HEXDUMP_DEBUG("TUYA_BLE_CB_EVT_DP_QUERY", event->dp_query_data.p_data, event->dp_query_data.data_len);
        } break;
        
        case TUYA_BLE_CB_EVT_OTA_DATA: {   TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_OTA_DATA");
            tuya_ble_ota_handler(&event->ota_data);
        } break;
        
        case TUYA_BLE_CB_EVT_BULK_DATA: {    TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_BULK_DATA");
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_BULK_DATA");
//            tuya_ble_bulk_data_demo_handler(&event->bulk_req_data);
        } break;
        
        case TUYA_BLE_CB_EVT_DATA_PASSTHROUGH: {   TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_DATA_PASSTHROUGH");
#if TUYA_BLE_SDK_TEST
            tuya_ble_sdk_test_send(TY_UARTV_CMD_PASSTHROUGH_WRITE, event->ble_passthrough_data.p_data, event->ble_passthrough_data.data_len);
#endif
        } break;
        
        case TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE: {  TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE");
#if TUYA_BLE_SDK_TEST
            uint8_t  rsp_data[2] = {1};
            uint32_t rsp_len = 2;
            rsp_data[1] = event->weather_req_response_data.status;
            tuya_ble_sdk_test_send(TY_UARTV_CMD_GET_WEATHER, rsp_data, rsp_len);
            TUYA_APP_LOG_INFO("received weather data request response result code =%d",event->weather_req_response_data.status);
#endif
        } break;
            
        case TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED: {   TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED");
#if TUYA_BLE_SDK_TEST
            tuya_ble_wd_object_t *object;
            uint16_t object_len = 0;
            for (;;) {
                object = (tuya_ble_wd_object_t *)(event->weather_received_data.p_data + object_len);

                TUYA_APP_LOG_DEBUG("recvived weather data, n_days=[%d] key=[0x%08x] val_type=[%d] val_len=[%d]", \
                                object->n_day, object->key_type, object->val_type, object->value_len); 
                TUYA_APP_LOG_HEXDUMP_DEBUG("vaule :", (uint8_t *)object->vaule, object->value_len);	

                // TODO .. YOUR JOBS 
                
                object_len += (sizeof(tuya_ble_wd_object_t) + object->value_len);
                if (object_len >= event->weather_received_data.data_len)
                    break;
            }
            
            tuya_ble_sdk_test_send(TY_UARTV_CMD_GET_WEATHER, event->weather_received_data.p_data, event->weather_received_data.data_len);
#endif
        } break;
            
        case TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID: {  TUYA_APP_LOG_DEBUG("TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID");
        } break;
        
        default: {
            TUYA_APP_LOG_INFO("tuya_ble_sdk_callback unknown event type 0x%04x", event->evt);
        } break;
    }
    TUYA_APP_LOG_DEBUG("callback over");
}

/*********************************************************
FN: 
*/
void tuya_ble_sdk_demo_init(void)
{
    memcpy(tuya_ble_device_param.device_id,       device_id_test, DEVICE_ID_LEN);
    memcpy(tuya_ble_device_param.auth_key,        auth_key_test,  AUTH_KEY_LEN);
    memcpy(tuya_ble_device_param.mac_addr_string, TY_DEVICE_MAC,  MAC_STRING_LEN);
    memcpy(tuya_ble_device_param.product_id,      TY_DEVICE_PID,  tuya_ble_device_param.product_id_len);
    memcpy(tuya_ble_device_param.adv_local_name,  TY_DEVICE_NAME, tuya_ble_device_param.adv_local_name_len);
    tuya_ble_sdk_init(&tuya_ble_device_param);
    
    tuya_ble_callback_queue_register(tuya_ble_sdk_callback);
    
//    tuya_ble_uart_common_init();
    
//    tuya_ble_ota_init();
//    tuya_ble_disconnect_and_reset_timer_init();
    tuya_ble_update_conn_param_timer_init();
    
    extern tuya_ble_parameters_settings_t tuya_ble_current_para;
    log_debug("auth key=%.32s\n", tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN);
    log_debug("device id=%.16s\n", tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN);
}

/*********************************************************
FN: 
*/
static void tuya_ble_app_data_process(int32_t evt_id, void *data)
{
    custom_evt_data_t* custom_data = data;
    
    switch (evt_id)
    {
        case APP_EVT_0: {
        } break;
        
        case APP_EVT_1: {
        } break;
        
        case APP_EVT_2: {
        } break;
        
        case APP_EVT_3: {
        } break;
        
        case APP_EVT_4: {
        } break;
        
        default: {
        } break;
    }
    
    if(custom_data != NULL) {
        tuya_ble_free((void*)custom_data);
    }
}

/*********************************************************
FN: no data
*/
void tuya_ble_custom_evt_send(custom_evtid_t evtid)
{
    tuya_ble_custom_evt_t custom_evt;
    
    custom_evt.evt_id = evtid;
    custom_evt.data = NULL;
    custom_evt.custom_event_handler = tuya_ble_app_data_process;
    
    tuya_ble_custom_event_send(custom_evt);
}

/*********************************************************
FN: 
*/
void tuya_ble_custom_evt_send_with_data(custom_evtid_t evtid, void* buf, uint32_t size)
{
    custom_evt_data_t* custom_data = tuya_ble_malloc(sizeof(custom_evt_data_t) + size);
    if(custom_data) {
        tuya_ble_custom_evt_t custom_evt;
        
        custom_data->len = size;
        memcpy(custom_data->value, buf, size);
        
        custom_evt.evt_id = evtid;
        custom_evt.data = custom_data;
        custom_evt.custom_event_handler = tuya_ble_app_data_process;
        
        tuya_ble_custom_event_send(custom_evt);
    } else {
        TUYA_APP_LOG_ERROR("tuya_ble_custom_evt_send_with_data: malloc failed");
    }
}

/*********************************************************
FN: 
*/
static void tuya_ble_disconnect_and_reset_timer_cb(tuya_ble_timer_t timer)
{
    tuya_ble_gap_disconnect();
    tuya_ble_device_delay_ms(100);
    tuya_ble_device_reset();
}

/*********************************************************
FN: 
*/
static void tuya_ble_update_conn_param_timer_cb(tuya_ble_timer_t timer)
{
    ty_ble_set_conn_param(TY_CONN_INTERVAL_MIN, TY_CONN_INTERVAL_MAX, 0, 6000);
}

/*********************************************************
FN: 
*/
void tuya_ble_disconnect_and_reset_timer_init(void)
{
    tuya_ble_timer_create(&disconnect_timer, 1000, TUYA_BLE_TIMER_SINGLE_SHOT, tuya_ble_disconnect_and_reset_timer_cb);
}

/*********************************************************
FN: 
*/
void tuya_ble_update_conn_param_timer_init(void)
{
    tuya_ble_timer_create(&update_conn_param_timer, 1000, TUYA_BLE_TIMER_SINGLE_SHOT, tuya_ble_update_conn_param_timer_cb);
//    tuya_ble_timer_create(&lock_timer_delay_report_timer, 200, TUYA_BLE_TIMER_SINGLE_SHOT, delay_report_outtime_handler);
}

/*********************************************************
FN: 
*/
void tuya_ble_disconnect_and_reset_timer_start(void)
{
    tuya_ble_timer_start(disconnect_timer);
}

/*********************************************************
FN: 
*/
void tuya_ble_update_conn_param_timer_start(void)
{
    tuya_ble_timer_start(update_conn_param_timer);
}








